﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;

namespace BattleTank3D
{
    class Tank
    {
        //A direção das rodas
        float cannonRotationValue;
        Model canhao;
        Model tankbase;
        Camera camera;
        Camera mapCamera;

        List<Tiro> listaTiros = new List<Tiro>();
        double ultimoTiroDado = 0;
        Texture2D texturaTiro;

        //TODO rever o uso desses atributos, uma vez que provisoriamente estão sendo utilizados para o tratamento de colisão
        Viewport defaultViewport;
        Viewport mapViewport;

        Effect efeito;

        #region Constructor
        public Tank(Viewport defaultViewport, Viewport mapViewport)
        {
            cannonRotationValue = 0.0f;
            camera = new Camera(defaultViewport);
            mapCamera = new Camera(mapViewport);
            this.defaultViewport = defaultViewport;
            this.mapViewport = mapViewport;
        }
        #endregion

        public void reset()
        {
            cannonRotationValue = 0.0f;
            camera = new Camera(defaultViewport);
            mapCamera = new Camera(mapViewport);
        }

        public void Load(ContentManager content)
        {
            canhao = content.Load<Model>("Modelos/Tank_Torre");
            tankbase = content.Load<Model>("Modelos/Tank_Base");
            texturaTiro = content.Load<Texture2D>("Modelos/Tiro");
            efeito = content.Load<Effect>("Efeitos/effects");
        }

        public void Update(GameTime gameTime)
        {
            KeyboardState teclaPressionada = Keyboard.GetState();

            if (teclaPressionada.IsKeyDown(Keys.Left))
            {
                this.cannonRotationValue += .01f;
            }
            if (teclaPressionada.IsKeyDown(Keys.Right))
            {
                this.cannonRotationValue -= .01f;
            }

            if ((teclaPressionada.IsKeyDown(Keys.Space)))
            {
                double tempoAtual = gameTime.TotalGameTime.TotalMilliseconds;
                if (tempoAtual - ultimoTiroDado > 100)
                {
                    Tiro novoTiro = new Tiro();
                    novoTiro.posicao = this.camera.getAvatarPosition();                                   
                    //novoTiro.rotacao = cannonRotationValue;
                    novoTiro.texturaTiro = texturaTiro;
                    listaTiros.Add(novoTiro);

                    ultimoTiroDado = tempoAtual;
                }
            }

            this.camera.Update();
            this.mapCamera.Update();

            this.AtualizaPosicaoTiro();
   
        }

        private void AtualizaPosicaoTiro()
        {
            for (int i = 0; i < listaTiros.Count; i++)
            {
                Tiro tiroAtual = listaTiros[i];
                MoverParaFrente(ref tiroAtual.posicao, this.camera.forwardSpeed * 2.0f);
                listaTiros[i] = tiroAtual;
            }
        }

        private void MoverParaFrente(ref Vector3 posicao,  float velocidade)
        {
            Vector3 adicionaVetor = Vector3.Transform(new Vector3(0, 0, -1),this.camera.getProj());
            posicao += adicionaVetor * velocidade;
        }

        public void Draw(GraphicsDevice dispositivoGrafico)
        {
            this.camera.Draw();

            this.tankbase.Draw(Matrix.CreateTranslation(this.camera.getAvatarPosition())
                , this.camera.getView(), this.camera.getProj());

            this.canhao.Draw(Matrix.CreateRotationY(cannonRotationValue + camera.getAvatarYaw())
                                   * Matrix.CreateTranslation(camera.getAvatarPosition())
                , camera.getView(), camera.getProj());

            this.DrawTiros(dispositivoGrafico);
        }

        public void DrawMap()
        {
            mapCamera.setCameraState(2);
            mapCamera.Draw();
        }

        public Vector3 getPosition()
        {
            return this.camera.getAvatarPosition();
        }

        public Matrix getView()
        {
            return camera.getView();
        }

        public Matrix getProj()
        {
            return camera.getProj();
        }

        public Matrix getMapView()
        {
            return mapCamera.getView();
        }

        public Matrix getMapProj()
        {
            return mapCamera.getProj();
        }



        private void DrawTiros(GraphicsDevice dispositivoGrafico)
        {
            if (listaTiros.Count > 0)
            {
                VertexPositionTexture[] bulletVertices = new VertexPositionTexture[listaTiros.Count * 6];
                int i = 0;
                foreach (Tiro tiroAtual in listaTiros)
                {
                    Vector3 center = tiroAtual.posicao;

                    bulletVertices[i++] = new VertexPositionTexture(center, new Vector2(1, 1));
                    bulletVertices[i++] = new VertexPositionTexture(center, new Vector2(0, 0));
                    bulletVertices[i++] = new VertexPositionTexture(center, new Vector2(1, 0));

                    bulletVertices[i++] = new VertexPositionTexture(center, new Vector2(1, 1));
                    bulletVertices[i++] = new VertexPositionTexture(center, new Vector2(0, 1));
                    bulletVertices[i++] = new VertexPositionTexture(center, new Vector2(0, 0));
                }

                efeito.CurrentTechnique = efeito.Techniques["PointSprites"];
                efeito.Parameters["xWorld"].SetValue(Matrix.CreateRotationY(cannonRotationValue + camera.getAvatarYaw())* Matrix.CreateTranslation(camera.getAvatarPosition()));
                efeito.Parameters["xProjection"].SetValue(this.camera.getProj());
                efeito.Parameters["xView"].SetValue(this.camera.getView());
                efeito.Parameters["xCamPos"].SetValue(this.camera.getAvatarPosition());
                efeito.Parameters["xTexture"].SetValue(texturaTiro);
                efeito.Parameters["xCamUp"].SetValue(new Vector3(0.0f, 1.0f, 0.0f));
                efeito.Parameters["xPointSpriteSize"].SetValue(0.1f);

                dispositivoGrafico.BlendState = BlendState.Additive;

                foreach (EffectPass pass in efeito.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    dispositivoGrafico.DrawUserPrimitives(PrimitiveType.TriangleList, bulletVertices, 0, listaTiros.Count * 2);
                }

                dispositivoGrafico.BlendState = BlendState.Opaque;
               
            }
        }
    }
}
